﻿/*****************************************************************//**
 * @file    FITKGraphObjectSketchInteractivePreviewer.h
 * @brief   Graph object for previewing the sketch interaction.
 *  
 * @author  ChengHaotian (yeguangbaozi@foxmail.com)
 * @date    2024-12-06
 *********************************************************************/

#ifndef __FITKGRAPHOBJECTSKETCHINTERACTIVEPREVIEWER_H__
#define __FITKGRAPHOBJECTSKETCHINTERACTIVEPREVIEWER_H__

#include "FITKGraphObject3D.h"

#include "FITKVTKGraphAdaptorAPI.h"

#include <QList>
#include <QVariant>

 /**
  * @brief   The shape type of the interactive modeling.
  * @author  ChengHaotian (yeguangbaozi@foxmail.com)
  * @date    2024-12-06
  */
enum SketchShapeType
{
    SST_NONE = -1,

    // Shape.
    SST_Vertex = 0,
    SST_Wire,
    SST_Rect,
    SST_Circle,
    SST_Ellipse,
    SST_ArcOfTan,
    SST_ArcOfCircle,
    SST_ArcOfP3,
    SST_Spline,

    // Construction.
    SST_ConLine,
    SST_ConHLine,
    SST_ConVLine,
    SST_ConAngleLine,
    SST_ConCircle,

};

// Forward declaration
class vtkUnstructuredGrid;
class vtkPoints;
class vtkVector3d;

class FITKGraphActor;

namespace Exchange
{
    /**
     * @brief   Graph object for the previewing the sketch interaction.
     * @author  ChengHaotian (yeguangbaozi@foxmail.com)
     * @date    2024-12-06
     */
    class FITKVTKGRAPHADAPTORAPI FITKGraphObjectSketchInteractivePreviewer : public FITKGraphObject3D
    {
        // Regist
        FITKGraphObjectRegist(FITKGraphObjectSketchInteractivePreviewer, FITKGraphObject3D);
        FITKCLASS(Exchange, FITKGraphObjectSketchInteractivePreviewer);

        Q_OBJECT

    public:
        /**
         * @brief   Constructor.
         * @param   caseData: The case data
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        FITKGraphObjectSketchInteractivePreviewer(AbaqusData::FITKDataCase* caseData);

        /**
         * @brief   Destructor.[virtual]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        virtual ~FITKGraphObjectSketchInteractivePreviewer();

        /**
         * @brief   Unused.[override]
         * @return  Is the graph object valid
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2025-01-21
         */
        bool isValid() override
        {
            return true;
        }

        /**
         * @brief   Update the visibility with data object's visibility.[override]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void updateVisibility() override;

        /**
         * @brief   Update all graph actors.[override]
         * @param   forceUpdate: Force update[default]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void update(bool forceUpdate = false) override;

        /**
         * @brief   Get the visibility from the data object.[override]
         * @return  The visibility
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool getDataVisibility() override;

        /**
         * @brief   Add a pressed position for modeling.
         * @param   pos: The world position
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void addPressedPosition(double* pos);

        /**
         * @brief   Add a hovered position for previewing.
         * @param   pos: The world position
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void addPreviewedPosition(double* pos);

        /**
         * @brief   Try to remove the last pressed position for modeling.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void removeLastPressedPosition();

        /**
         * @brief   Set the current shape type.
         * @param   type: Shape type
         * @param   param: The additional parameter for modeling[default]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void setShapeType(SketchShapeType type, QVariant param = QVariant());

        /**
         * @brief   Initialize the plane for modeling.
         * @param   pos: The plane center
         * @param   nor: The plane normal
         * @param   up: The plane up direction
         * @param   right: The plane right direction
         * @param   size: The size of the sketch[default]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void setPlane(double* pos, double* nor, double* up, double* right, double size = 200.);

        /**
         * @brief   Clear all points and cells in the previewing grid dataset.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void clearData();

        /**
         * @brief   Get the path positions.
         * @return  The valid positions
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-09
         */
        QVector<double> getPathPositions();

        /**
         * @brief   End the sketch modeling mode.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-09
         */
        void endSketch();

    signals:
        /**
         * @brief   Signal - For GUI, the signal for modeling finished.
         * @param   poses: The positions for modeling finished
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void sig_modelingFinished(QVector<double> poses);

        /**
         * @brief   Signal - For GUI, a new valid pressed position had been added to the path position list.
         * @param   poses: All the pressed positions
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-09
         */
        void sig_validPressed(QVector<double> poses);

    private:
        /**
         * @brief   Initialize.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void init();

        /**
         * @brief   Generate the grid actors.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void generateGraph();

        /**
         * @brief   Disable the light properties.
         * @param   fActor: The actor
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void disableLightShadow(FITKGraphActor* fActor);

        /**
         * @brief   Modeling with the positions.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void modeling();

        /**
         * @brief   Finish drawing, for dealing with the position list.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void finishModeling();

        // Modeling.
        //@{
        /**
         * @brief   Draw vertex.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool drawVertex();

        /**
         * @brief   Draw wire.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool drawWire();

        /**
         * @brief   Draw rect.
         * @return  Finish flag  
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool drawRect();

        /**
         * @brief   Draw circle.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool drawCircle();

        /**
         * @brief   Draw ellipse.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool drawEllipse();

        /**
         * @brief   Draw arc( part of the circle ).
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool drawArcCircle();

        /**
         * @brief   Draw arc with two points.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool drawArcTan();

        /**
         * @brief   Draw arc with three points.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        bool drawArcThreePoints();

        /**
         * @brief   Draw spline.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-09
         */
        bool drawSpline();
        //@}

        // Construction.
        //@{
        /**
         * @brief   Draw construction line.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-30
         */
        bool drawConLine();

        /**
         * @brief   Draw construction horizontal line.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-30
         */
        bool drawConHLine();

        /**
         * @brief   Draw construction vertical line.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-30
         */
        bool drawConVLine();

        /**
         * @brief   Draw construction angle line.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-31
         */
        bool drawConAngleLine();

        /**
         * @brief   Draw construction circle.
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-30
         */
        bool drawConCircle();
        //@}

        // Tool function for modeling.
        //@{
        /**
         * @brief   Draw arc by two or three points.
         * @param   oPoses: The returned positions of the arc
         *          Center + Start + End[quote]
         * @return  Finish flag( not the finish flag for GUI, this flag means the modeling
         *          finished with both pressed positions and preview positions. )
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-10
         */
        bool drawArcByCirclePoints(QList<vtkVector3d> & oPoses);

        /**
         * @brief   Draw line with two positions, return the two positions on the edge of the grids.
         * @param   iPoses: The input and output positions[quote]
         * @return  Finish flag
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-30
         */
        bool drawLineByTwoPoints(QList<vtkVector3d> & ioPoses);
        //@}

        /**
         * @brief   Get the cross point of the two lines.
         * @param   iP1: The point 1 on line 1
         * @param   iP2: The point 2 on line 1
         * @param   iP3: The point 1 on line 2
         * @param   iP4: The point 2 on line 2
         * @param   oPx: The returned cross point
         * @param   oT1: The output parameter on line 1[quote]
         * @return  Whether the two lines has a valid cross point
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-19
         */
        bool getCrossPoint(double* iP1, double* iP2, double* iP3, double* iP4, double* oPx, double & oT1);

    private:
        /**
         * @brief   The grid data for the previewed wireframe.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        vtkUnstructuredGrid* m_ugrid{ nullptr };

        /**
         * @brief   The points data for the previewed wireframe.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        vtkPoints* m_points{ nullptr };

        /**
         * @brief   The actor for the previewed wireframe.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        FITKGraphActor* m_fActor{ nullptr };

        /**
         * @brief   The pressed position list for modeling.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        QList<vtkVector3d> m_pressedPoses;

        /**
         * @brief   The hovered position list for modeling.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        QList<vtkVector3d> m_previewedPoses;

        /**
         * @brief   Current shape type.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        SketchShapeType m_shapeType = SketchShapeType::SST_NONE;

        /**
         * @brief   The additional parameter for modeling.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-31
         */
        QVariant m_shapeParam = QVariant();

        /**
         * @brief   The position of the modeling plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        double m_planePos[3]{ 0., 0., 0. };

        /**
         * @brief   The normal of the modeling plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        double m_planeNor[3]{ 0., 0., 0. };

        /**
         * @brief   The up direction of the modeling plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        double m_planeUp[3]{ 0., 0., 0. };

        /**
         * @brief   The right direction of the modeling plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        double m_planeRight[3]{ 0., 0., 0. };

        /**
         * @brief   The default size of the modeling plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-30
         */
        double m_size = 200.;

        // Addin.
        //@{
        /**
         * @brief   Addintion value for different type of shape.
         *          While making a wire, this value save the first pressed position.
         *          While making an arc, this value defines the direction of the mouse move,
         *          if the value is 'true', the direction is anti-clockwised, else, the direction
         *          is clockwised.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        QVariant m_val = QVariant();

        /**
         * @brief   The last arc degree.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        double m_lastArcDeg = 0.;
        //@}

    };
}   // namespace Exchange

// Regist vtk type.
// Q_DECLARE_METATYPE(vtkVector3d, "vtkVector3d");

#endif // __FITKGRAPHOBJECTSKETCHINTERACTIVEPREVIEWER_H__
